package com.fishingwithme.android.data.network

import com.fishingwithme.android.data.model.AddCircleDto
import com.fishingwithme.android.data.model.Agr
import com.fishingwithme.android.data.model.ApiAuthResponse
import com.fishingwithme.android.data.model.ApiResponse
import com.fishingwithme.android.data.model.ApproveRuleItem
import com.fishingwithme.android.data.model.AuditCircle
import com.fishingwithme.android.data.model.AuditRequestDto
import com.fishingwithme.android.data.model.Auditor
import com.fishingwithme.android.data.model.BaseInfo
import com.fishingwithme.android.data.model.CandidateUser
import com.fishingwithme.android.data.model.CircleAuditAdd
import com.fishingwithme.android.data.model.CircleDetail
import com.fishingwithme.android.data.model.CircleMessage
import com.fishingwithme.android.data.model.CirclePageDto
import com.fishingwithme.android.data.model.City
import com.fishingwithme.android.data.model.Comment
import com.fishingwithme.android.data.model.CreditAction
import com.fishingwithme.android.data.model.CreditAvailable
import com.fishingwithme.android.data.model.CreditLevelRule
import com.fishingwithme.android.data.model.FishingRecord
import com.fishingwithme.android.data.model.HarvestApprovalDto
import com.fishingwithme.android.data.model.HarvestRecordDto
import com.fishingwithme.android.data.model.HarvestSubmission
import com.fishingwithme.android.data.model.Line
import com.fishingwithme.android.data.model.LoginUserDto
import com.fishingwithme.android.data.model.MyCircleDto
import com.fishingwithme.android.data.model.MyHarvestDto
import com.fishingwithme.android.data.model.MySpotDto
import com.fishingwithme.android.data.model.PageResponse
import com.fishingwithme.android.data.model.PointsRecord
import com.fishingwithme.android.data.model.PolygonOrigin
import com.fishingwithme.android.data.model.Position
import com.fishingwithme.android.data.model.RegisterRequest
import com.fishingwithme.android.data.model.RegisterResponse
import com.fishingwithme.android.data.model.RuleItem
import com.fishingwithme.android.data.model.Spot
import com.fishingwithme.android.data.model.SpotAddDTO
import com.fishingwithme.android.data.model.SpotApprovalDto
import com.fishingwithme.android.data.model.SpotDetail
import com.fishingwithme.android.data.model.SpotInCircleDto
import com.fishingwithme.android.data.model.SpotProperty
import com.fishingwithme.android.data.model.SpotUpdateDTO
import com.fishingwithme.android.data.model.UserCredit
import okhttp3.MultipartBody
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Headers
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.Part
import retrofit2.http.Query
import retrofit2.http.QueryMap

interface FishingApiService {

    // Audit API
    @POST("mgr/audit-spot")
    suspend fun auditSpot(
        @Body auditRequest: AuditRequestDto
    ): Response<ApiResponse<Int>>


    // Circle and Location APIs
    @GET("circle/getCity")
    suspend fun getCityByPosition(
        @Query("latitude") latitude: Double,
        @Query("longitude") longitude: Double
    ): Response<ApiResponse<City>>

    @GET("circle/searchCities")
    @Headers("Need-Token: false")
    suspend fun searchCities(
        @Query("keyword") keyword: String
    ): Response<ApiResponse<List<City>>>

    @GET("circle/list")
    suspend fun getCircles(
        @Query("pageNum") pageNum: Int,
        @Query("pageSize") pageSize: Int,
        @Query("title") title: String? = null,
        @Query("cityCode") cityCode: String? = null,
        @Query("isActive") isActive: Boolean? = null
    ): Response<PageResponse<CirclePageDto>>

    @GET("circle/getCircleLocations")
    suspend fun getCircleLocations(
        @Query("latitude") latitude: Double,
        @Query("longitude") longitude: Double
    ): Response<ApiResponse<List<PolygonOrigin>>>

    @POST("circle/add")
    suspend fun addCircle(
        @Body circle: AddCircleDto
    ): Response<ApiResponse<String>>

    @GET("circle/delete")
    suspend fun deleteCircle(
        @Query("id") id: String
    ): Response<ApiResponse<String>>

    @GET("circle/markActive")
    suspend fun markActive(
        @QueryMap data: Map<String, String>
    ): Response<ApiResponse<String>>

    @POST("circle/message")
    suspend fun sendCircleMessage(
        @Body request: Map<String, String>
    ): Response<ApiResponse<String>>

    // Circle Messages
    @Headers("Need-Token: false")
    @GET("circle-messages/quasi-realtime")
    suspend fun loadCircleMessages(
        @Query("cityCode") cityCode: String
    ): Response<List<CircleMessage<*>>>

    @Headers("Need-Token: false")
    @GET("circle-messages/non-realtime")
    suspend fun loadBackwardMessages(
        @Query("cityCode") cityCode: String,
        @Query("cursor") cursor: String,
        @Query("isForward") isForward: Boolean = false
    ): Response<ApiResponse<List<CircleMessage<*>>>>

    @Headers("Need-Token: false")
    @GET("circle-messages/non-realtime")
    suspend fun loadForwardMessages(
        @Query("cityCode") cityCode: String,
        @Query("cursor") cursor: String,
        @Query("isForward") isForward: Boolean = true
    ): Response<ApiResponse<List<CircleMessage<*>>>>

    // Spot APIs
    @Headers("Need-Token: false")
    @GET("spot/v2/getSpotsByLocation")
    suspend fun loadSpots(
        @Query("latitude") latitude: Double,
        @Query("longitude") longitude: Double
    ): Response<List<Spot>>

    @GET("spot/getUserSpots")
    suspend fun loadUserSpots(
        @Query("latitude") latitude: Double,
        @Query("longitude") longitude: Double
    ): Response<ApiResponse<List<Spot>>>

    @GET("spot/getSecretSpots")
    suspend fun loadSecretSpots(
        @Query("latitude") latitude: Double,
        @Query("longitude") longitude: Double
    ): Response<ApiResponse<List<Spot>>>

    @GET("spot/getSpot")
    suspend fun loadDiscoverSpot(
        @Query("spotId") spotId: String
    ): Response<ApiResponse<Spot>>

    @GET("spot/getUserSpot")
    suspend fun loadUserSpot(
        @Query("spotId") spotId: String
    ): Response<SpotDetail>

    @GET("spot/getLatest")
    suspend fun loadUserLatestSpot(): Response<ApiResponse<Spot>>

    @GET("spot/getUpdateSpot")
    suspend fun getUpdateSpot(
        @Query("spotId") spotId: String
    ): Response<ApiResponse<Spot>>

    @POST("spot/checkSpotExists")
    suspend fun checkExists(
        @Body location: Position
    ): Response<ApiResponse<Boolean>>

    @POST("spot/addSpot")
    suspend fun addSpot(
        @Body spot: SpotAddDTO
    ): Response<ApiResponse<String>>

    @POST("spot/updateSpot")
    suspend fun updateSpot(
        @Body spot: SpotUpdateDTO
    ): Response<ApiResponse<String>>

    @GET("spot/collect")
    suspend fun collectSpot(
        @Query("spotId") spotId: String
    ): Response<ApiResponse<String>>

    @GET("spot/v2/collected")
    suspend fun getSpotPage(
        @Query("pageNum") pageNum: Int,
        @Query("pageSize") pageSize: Int,
        @Query("isCollected") isCollected: Boolean
    ): Response<PageResponse<MySpotDto>>

    @GET("spot/myHarvests")
    suspend fun getMyHarvests(
        @Query("pageNum") pageNum: Int,
        @Query("pageSize") pageSize: Int
    ): Response<PageResponse<MyHarvestDto>>
    @GET("circle/myCircles")
    suspend fun getMyCircles(
        @Query("pageNum") pageNum: Int,
        @Query("pageSize") pageSize: Int
    ): Response<PageResponse<MyCircleDto>>
    @GET("mgr/getApprovalSpots")
    suspend fun getApprovalSpots(
        @Query("pageNum") pageNum: Int,
        @Query("pageSize") pageSize: Int,
        @Query("disabled") disabled: Boolean
    ): Response<PageResponse<SpotApprovalDto>>

    @GET("mgr/maintainer/auditors")
    suspend fun getAuditorPage(
        @Query("pageNum") pageNum: Int,
        @Query("pageSize") pageSize: Int,
        @Query("disabled") disabled: Boolean
    ): Response<PageResponse<Auditor>>

    @GET("spot/getUserMgrSpots")
    suspend fun loadUserMgrSpots(
        @Query("pageNum") pageNum: Int,
        @Query("pageSize") pageSize: Int
    ): Response<ApiResponse<PageResponse<Spot>>>

    @GET("spot/getProps")
    suspend fun loadAddSpotProperties(): Response<SpotProperty>

    @POST("spot/querySpots")
    suspend fun queryUserSpots(
        @Body request: Map<String, String>
    ): Response<ApiResponse<List<Spot>>>

    @GET("spot/search")
    @Headers("Need-Token: false")
    suspend fun searchSpots(
        @Query("queryStr") queryStr: String
    ): Response<ApiResponse<List<Spot>>>

    @GET("spot/getSpotNavLine")
    suspend fun loadSpotNavigationInfo(
        @Query("spotId") spotId: String
    ): Response<Line>

    // Harvest and Fishing Records
    @GET("spot/getSpotHarvests")
    suspend fun loadSpotVisitors(
        @Query("pageNum") pageNum: Int,
        @Query("pageSize") pageSize: Int,
        @Query("spotId") spotId: String
    ): Response<PageResponse<HarvestRecordDto>>

    @Headers("Need-Token: false")
    @GET("spot/v2/getHarvest")
    suspend fun loadHarvest(
        @Query("id") id: String
    ): Response<FishingRecord>

    @GET("spot/getApproveHarvest")
    suspend fun loadApproveHarvest(
        @Query("id") id: String
    ): Response<FishingRecord>

    @POST("spot/addVisitHarvest")
    suspend fun addVisitHarvest(
        @Body data: HarvestSubmission
    ): Response<Void>

    @GET("spot/harvest/likes")
    suspend fun harvestLike(
        @Query("harvestId") harvestId: String
    ): Response<ApiResponse<String>>

    @GET("spot/harvest/dislike")
    suspend fun harvestDislike(
        @Query("harvestId") harvestId: String
    ): Response<ApiResponse<String>>

    // Comments
    @GET("spot/getComments")
    suspend fun getSpotCommentPage(
        @Query("pageNum") pageNum: Int,
        @Query("pageSize") pageSize: Int,
        @Query("spotId") spotId: String
    ): Response<PageResponse<Comment>>

    @GET("comments/list")
    suspend fun loadHarvestComments(
        @Query("targetId") targetId: String,
        @Query("targetType") targetType: String,
        @Query("pageNum") pageNum: Int,
        @Query("pageSize") pageSize: Int
    ): Response<ApiResponse<PageResponse<Comment>>>

    @POST("comments/add")
    suspend fun commentHarvest(
        @Body comment: Comment
    ): Response<ApiResponse<String>>

    @GET("comments/like")
    suspend fun likeComment(
        @Query("commentId") commentId: String
    ): Response<ApiResponse<String>>

    @GET("comments/unlike")
    suspend fun unlikeComment(
        @Query("commentId") commentId: String
    ): Response<ApiResponse<String>>

    // Credit System
    @GET("credit/get")
    suspend fun getUserCredit(): Response<UserCredit>

    @GET("credit/getCreditRules")
    suspend fun getCreditRules(
        @QueryMap data: Map<String, String>
    ): Response<PageResponse<RuleItem>>

    @GET("credit/records/list")
    suspend fun getCreditRecords(
        @QueryMap data: Map<String, String>
    ): Response<PageResponse<PointsRecord>>

    @GET("credit/getCreditLvls")
    suspend fun getCreditLvls(): Response<ApiResponse<List<CreditLevelRule>>>

    @GET("credit/skipAds")
    suspend fun setAutoSkipAds(
        @Query("skipAds") skipAds: Boolean
    ): Response<ApiResponse<String>>

    @GET("credit/setCredit")
    suspend fun setSpotCredit(
        @Query("spotId") spotId: String,
        @Query("credit") credit: Int
    ): Response<ApiResponse<String>>

    @GET("credit/isCreditAvailable")
    suspend fun checkCreditAvailable(
        @Query("spotId") spotId: String
    ): Response<ApiResponse<CreditAvailable>>

    // User Management
    @POST("user/login")
    suspend fun login(
        @Body credentials: Map<String, String>
    ): Response<ApiAuthResponse<LoginUserDto>>

    @POST("user/register")
    suspend fun register(
        @Body request: RegisterRequest
    ): Response<ApiResponse<RegisterResponse>>

    @POST("user/cancel")
    suspend fun cancelUser(): Response<ApiResponse<String>>

    @POST("user/saveUserGender")
    suspend fun saveUserGender(
        @Body request: Map<String, String>
    ): Response<ApiResponse<String>>

    @POST("user/saveUserEmail")
    suspend fun saveUserEmail(
        @Body request: Map<String, String>
    ): Response<ApiResponse<String>>

    @POST("user/saveUserAvatar")
    suspend fun saveUserAvatar(
        @Body request: Map<String, String>
    ): Response<ApiResponse<String>>

    @POST("user/saveUserNickName")
    suspend fun saveUserNickName(
        @Body request: Map<String, String>
    ): Response<ApiResponse<String>>

    @POST("user/emailVerify")
    suspend fun sendEmailConfirmingCode(
        @Body request: Map<String, String>
    ): Response<ApiResponse<String>>

    // Common APIs
    @GET("common/agr")
    suspend fun getAgrPp(
        @Query("type") type: String
    ): Response<ApiResponse<Agr>>

    @POST("common/fb/add")
    suspend fun addFeedback(
        @Body form: Map<String, String>
    ): Response<ApiResponse<String>>

    @GET("common/fb/types")
    suspend fun getFeedbackTypes(): Response<ApiResponse<List<BaseInfo>>>

    // File Upload
    @Multipart
    @POST("file/upload")
    suspend fun uploadFile(
        @Part file: MultipartBody.Part
    ): Response<ApiResponse<Map<String, String>>>

    // Add the new endpoint for fetching rules items
    @GET("rules/items")
    suspend fun getRulesItems(
        @Query("ruleId") ruleId: Int
    ): Response<ApiResponse<List<ApproveRuleItem>>>

    // Add the missing endpoint for harvest approvals
    @GET("mgr/getApprovalHarvests")
    suspend fun getApprovalHarvests(
        @Query("state") state: Boolean,
        @Query("pageNum") pageNum: Int,
        @Query("pageSize") pageSize: Int
    ): Response<PageResponse<HarvestApprovalDto>>

    // Add new endpoint for harvest approval
    @POST("mgr/audit-harvest")
    suspend fun auditHarvest(
        @Body auditRequest: AuditRequestDto
    ): Response<ApiResponse<Int>>

    // AddCircleAuditScreen APIs
    @GET("mgr/searchAuditCandidates")
    suspend fun searchAuditCandidates(
        @Query("nickname") nickname: String
    ): Response<ApiResponse<List<CandidateUser>>>

    @GET("mgr/searchCircleCandidates")
    suspend fun searchCircleCandidates(
        @Query("title") title: String
    ): Response<ApiResponse<List<AuditCircle>>>

    @POST("mgr/addCircleAudit")
    suspend fun addCircleAudit(
        @Body form: CircleAuditAdd
    ): Response<ApiResponse<Int>>

    @GET("credit/settings")
    suspend fun getPointSettings(): Response<ApiResponse<CreditAction>>

    @GET("circle/get")
    suspend fun getCircleDetail(@Query("id") id: String):
            Response<ApiResponse<CircleDetail>>

    @GET("circle/spots")
    suspend fun getCircleSpots(
        @Query("id") id: String,
        @Query("pageNum") pageNum: Int,
        @Query("pageSize") pageSize: Int
    ): Response<PageResponse<SpotInCircleDto>>

}